package com.mfks.service.impl;

import java.util.Date;
import java.util.Map;

import org.apache.commons.lang3.RandomUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.dubbo.config.annotation.Service;
import com.mfks.mapper.TMemberOrderMapper;
import com.mfks.model.TMember;
import com.mfks.model.TMemberOrder;
import com.mfks.service.MemberOrderService;
import com.mfks.service.MemberService;
import com.mfks.service.SysParamService;

import top.ibase4j.core.Constants;
import top.ibase4j.core.base.BaseServiceImpl;
import top.ibase4j.core.exception.BusinessException;
import top.ibase4j.core.support.generator.Sequence;
import top.ibase4j.core.support.pay.WxPay;
import top.ibase4j.core.support.pay.WxPayment;
import top.ibase4j.core.util.CacheUtil;
import top.ibase4j.core.util.DataUtil;
import top.ibase4j.core.util.DateUtil;
import top.ibase4j.core.util.DateUtil.DatePattern;
import top.ibase4j.core.util.InstanceUtil;
import top.ibase4j.core.util.PropertiesUtil;
import top.ibase4j.core.util.WeChatUtil;

/**
 * <p>
 * 订单信息 服务实现类
 * </p>
 *
 * @author ShenHuaJie
 * @since 2018-12-27
 */
@Service
@CacheConfig(cacheNames = "MemberOrder")
public class MemberOrderServiceImpl extends BaseServiceImpl<TMemberOrder, TMemberOrderMapper>
implements MemberOrderService {
    private SysParamService sysParamService;
    @Autowired
    private MemberService memberService;

    @Override
    @Transactional
    public Object create(TMemberOrder record) {
        if (DataUtil.isEmpty(record.getOrderNo())) {
            String time = "T" + DateUtil.getDateTime(DatePattern.YYYYMMDDHHMMSSSSS);
            record.setOrderNo(time + RandomUtils.nextInt(10, 99));
        }
        if ("1".equals(record.getBizType())) {
            record.setTradeType("2");
            if (DataUtil.isEmpty(record.getPayType())) {
                record.setPayType("1");
            }
            TMember member = memberService.queryById(record.getMemberId());
            String callBack = sysParamService.getValue("WX-PAY-CALLBACK");
            Map<String, String> sign = WeChatUtil.pushOrder(PropertiesUtil.getString("wx.applet.mch_id"),
                PropertiesUtil.getString("wx.applet.appId"), PropertiesUtil.getString("wx.applet.partnerKey"), "JSAPI",
                record.getOrderNo(), "购买钥匙-社交", member.getPhone(), record.getPayMoney(), null, record.getClientIP(),
                callBack, member.getWxOpenid());
            record.setPayOrderId(sign.get("prepayid"));
            if (DataUtil.isEmpty(record.getRemark())) {
                record.setRemark("购买钥匙-" + DataUtil.ifNull(member.getPhone(), member.getWxOpenid()));
            }
            super.update(record);
            return sign;
        } else if ("2".equals(record.getBizType())) {
            record.setTradeType("2");
            if (DataUtil.isEmpty(record.getRemark())) {
                record.setRemark("交友消费");
            }
            super.update(record);
            TMember member = memberService.queryById(record.getMemberId());
            if (member.getKeyNum() < record.getKeyNum()) {
                throw new BusinessException("剩余钥匙不足");
            }
            member.setKeyNum(member.getKeyNum() - record.getKeyNum());
            memberService.update(member);
            return null;
        } else if ("3".equals(record.getBizType())) {
            record.setTradeType("3");
            if (DataUtil.isEmpty(record.getRemark())) {
                record.setRemark("分享奖励");
            }
            super.update(record);
            TMember member = memberService.queryById(record.getMemberId());
            member.setKeyNum(member.getKeyNum() + record.getKeyNum());
            memberService.update(member);
            return null;
        }
        return null;
    }

    @Override
    public Map<String, String> updateOrderState(TMemberOrder order) {
        TMemberOrder record = super.selectOne(order);
        Map<String, String> params = WxPayment.buildParasMap(PropertiesUtil.getString("wx.appId"), null,
            PropertiesUtil.getString("wx.mch_id"), null, null, record.getOrderNo(),
            PropertiesUtil.getString("wx.partnerKey"));
        Map<String, String> resultMap = WxPayment.xmlToMap(WxPay.orderQuery(params));
        String return_code = resultMap.get("return_code");
        Map<String, String> map = InstanceUtil.newHashMap();
        if (WxPayment.codeIsOK(return_code)) {
            String result_code = resultMap.get("result_code");
            if (WxPayment.codeIsOK(result_code)) {
                String trade_state = resultMap.get("trade_state");
                if (WxPayment.codeIsOK(trade_state)) {
                    Date date = DateUtil.stringToDate(resultMap.get("time_end"));
                    record.setPayTime(date);
                    record.setPayOrderId(resultMap.get("transaction_id"));
                    record.setPayResult("1");
                    record.setPayOpenId(resultMap.get("openid"));
                    record = super.update(record);
                } else {
                    record.setPayResult("2");
                    record.setRemark(resultMap.get("trade_state_desc"));
                    map.put("remark", record.getRemark());
                    record = super.update(record);
                }
            } else {
                logger.warn(resultMap.get("err_code_des"));
            }
        } else {
            logger.warn(resultMap.get("return_msg"));
        }
        map.put("result", record.getPayResult());
        return map;
    }

    @Override
    @Transactional
    public void updateWxPayReturn(Map<String, Object> param) {
        Map<String, String> params = InstanceUtil.newHashMap();
        for (String key : param.keySet()) {
            params.put(key, param.get(key).toString());
        }
        String signStr = params.get("sign");
        String sign = WxPayment.createSign(params, PropertiesUtil.getString("wx.partnerKey"));
        if (!sign.equals(signStr)) {
            throw new RuntimeException("参数错误.");
        }
        String return_code = params.get("return_code");
        if (WxPayment.codeIsOK(return_code)) {
            String orderNo = params.get("out_trade_no");
            String requestId = Sequence.uuid();
            String key = Constants.CACHE_NAMESPACE_LOCK + "ORDER:" + orderNo;
            if (CacheUtil.getLock(key, requestId)) {
                try {
                    TMemberOrder order = new TMemberOrder();
                    order.setOrderNo(orderNo);
                    order = selectOne(order);
                    if (order == null) {
                        throw new RuntimeException("商户订单号错误.");
                    }
                    if ("0".equals(order.getPayResult())) {
                        order.setPayOrderId(params.get("transaction_id"));
                        order.setPayTime(DateUtil.stringToDate(params.get("time_end")));
                        order.setPayOpenId(params.get("openid"));
                        order.setPayResult("SUCCESS".equals(params.get("result_code")) ? "1" : "2");
                        super.update(order);
                        if ("1".equals(order.getBizType())) {
                            TMember member = memberService.queryById(order.getMemberId());
                            member.setKeyNum(member.getKeyNum() + order.getKeyNum());
                            memberService.update(member);
                        }
                    }
                } finally {
                    CacheUtil.unLock(key, requestId);
                }
            } else {
                throw new RuntimeException("稍候处理.");
            }
        }
    }
}
